package com.wt.demo.threadtest.frame;

import com.wt.demo.threadtest.flowline.AddOperate;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @description
 * @author: wangtao
 * @date:11:47 2018/6/11
 * @email:tao8.wang@changhong.com
 */
public class OperateExecutorManager {

    private static ExecutorService exec = Executors.newFixedThreadPool(10);

    public static OperateChain chain = new OperateChain();

    public static Comparator comparator;

    public static BlockingQueue<Object> firstOperateQueue;

    public static void addOperate(Operate operate) {
        chain.addOperate(operate);
    }

    public static void addOperates(List<Operate> operates) {
        chain.setOperates(operates);
    }

    public static ExecutorService getExec() {
        return exec;
    }

    public static void setExec(ExecutorService exec) {
        OperateExecutorManager.exec = exec;
    }

    public static OperateChain getChain() {
        return chain;
    }

    public static void setChain(OperateChain chain) {
        OperateExecutorManager.chain = chain;
    }

    public static void initOperate() {
        List<Operate> operates = chain.getOperates();
        operates.sort(comparator == null ? Comparator.comparing(Operate::getOrder) : comparator);
        Operate nextOperate = null;
        Operate currentOperate = null;
        for (int i = operates.size() - 1; i >= 0; i--) {
            currentOperate = operates.get(i);
            currentOperate.nextOperate = nextOperate;
            final Operate finalCurrentOperate = currentOperate;
            //这个地方用submit，死循环不会生效
            exec.execute(() -> {
                while (true) {
                    //队列会产生wait效果，这里直接用死循环就行，如果队列中没有值，在take的时候就会wait住
                    finalCurrentOperate.doOperate();
                }
            });
            nextOperate = currentOperate;
        }
        firstOperateQueue = operates.get(0).getQueue();
    }

    public static void handle(Object data){
        firstOperateQueue.add(data);
    }

}
